#include "types.h"
#include "defs.h"
#include "mm.h"
#include "constants.h"
#include "x86.h"
#include "proc.h"

extern char end[];
__attribute__((__aligned__(PGSIZE)))
    pde_t entrypgdir[NPTENTRIES] = {
// 线性地址 0, 4MB) --> 物理地址 [0, 4MB)
		[0] = (0) | PTE_P | PTE_W | PTE_PS,
		// 线性地址 [2G, 2G+4MB) --> 物理地址 [0, 4MB)
		[KERNBASE >> PDXSHIFT] = (0) | PTE_P | PTE_W | PTE_PS, };

int main(void) {
	showWelcome();
	kFreeVMInit(end, P2V(4*1024*1024), 1);
	kPageTableInit();  //只映射内核空间，即2G+,0-4M没有映射，若使用则会抛异常
	mpinit();          // 多处理器相关硬件信息初始化
	lapicinit();       //lapic中断相关初始化
	seginit();
	ioapicinit();
	consoleinit();
	printk("cpu%d start...\n", cpu->id);
	pinit();
	tvinit();
	startothers();
	kFreeVMInit(P2V(4*1024*1024), P2V(PHYSTOP), 0);
	userinit();
	mpmain();
	return 0;
}

void mpenter(void) {
	switchKVM();
	seginit();
	lapicinit();
	mpmain();
}

void mpmain(void) {
	printk("cpu%d: starting\n", cpu->id);
	idtinit();       // idt初始化
	xchg(&cpu->started, 1); // 提供给startothers函数里的while (c->started == 0)
	scheduler();     // start running processes
}

void startothers(void) {
	extern uchar _binary_entryother_start[], _binary_entryother_size[];
	uchar *code;
	struct cpu *c;
	char *stack;

	code = p2v(0x7000);
	memmove(code, _binary_entryother_start, (uint) _binary_entryother_size);

	for (c = cpus; c < cpus + ncpu; c++) {
		if (c == cpus + cpunum())  // 当前cpu已启动
			continue;

		stack = kAlloc();
		*(void**) (code - 4) = stack + KSTACKSIZE;
		*(void**) (code - 8) = mpenter;
		*(int**) (code - 12) = (void *) v2p(entrypgdir);

		lapicstartap(c->id, v2p(code));

		while (c->started == 0)
			;
	}
}

